import { defineComponent } from 'vue';
import type { PropType } from 'vue';
import { AppComponentBase } from '/@/shared/component-base';
import { FlatPermissionDto, PermissionServiceProxy } from '/@/shared/service-proxies';
import { arrayService } from '/@/shared/utils';
import { ReloadOutlined } from '@ant-design/icons-vue';
import { DataNode } from 'ant-design-vue/lib/tree';

export default defineComponent({
  components: {
    ReloadOutlined
  },
  mixins: [AppComponentBase],
  props: {
    /** 选中的数据 */
    defaultSelectedPermissions: {
      type: Object as PropType<string[]>,
      default: []
    }
  },
  emits: ['selectedPermissionsChange'],
  watch: {
    /** 选中数据发生改变 */
    defaultSelectedPermissions(val: string[]) {
      if (!Array.isArray(val)) {
        val = [];
      }
      this.arrToTreeNode(val);
    },
    /** 筛选条件发生改变 */
    filterText(val: string) {
      this.onFilterChange(val);
    }
  },
  data() {
    return {
      /** 所有权限 */
      permissions: [] as FlatPermissionDto[],
      /** 授权的权限 */
      grantedPermissionNames: [] as string[],
      /** 所有权限字典 */
      permissionsDict: {} as { [key: string]: FlatPermissionDto },
      /** 树数据 */
      treeData: new Array<DataNode>(),
      /** 展开的键 */
      expandedKeys: [] as string[],
      /** 自动展开父级 */
      autoExpandParent: true,
      /** 权限服务 */
      permissionService: new PermissionServiceProxy(),
      /** 筛选字符串 */
      filterText: '',
      /** 选中的权限 */
      checkedPermissions: [] as string[]
    };
  },
  mounted() {
    // 请求服务端数据
    this.loading = true;
    this.permissionService
      .getAllPermissions()
      .finally(() => {
        this.loading = false;
      })
      .then((result) => {
        this.permissions = result.items ?? [];

        // 处理数据
        this.permissionsDict = {};
        this.permissions.forEach((item: any) => {
          item.value = item.name;
          // 添加到字典
          this.permissionsDict[item.name] = item;
        });

        // 转树
        this.arrToTreeNode(this.getDefaultSelectedPermissions());
      });
  },
  methods: {
    /**
     * 数组重组为Tree数据
     */
    arrToTreeNode(grantedPermissionNames: string[]) {
      // 转换为树形数据
      this.treeData = arrayService.arrToTreeNode(this.permissions, {
        idMapName: 'name',
        parentIdMapName: 'parentName',
        titleMapName: 'displayName'
      });

      // 记录叶子节点的字典
      const leafPermissionDict: { [key: string]: boolean } = {};
      // 置空展开的节点
      this.expandedKeys = [];
      // 递归树
      arrayService.visitTree(this.treeData, (item) => {
        // 默认展开全部
        this.expandedKeys.push(item.key);
        // 叶子节点已选中
        if (item.isLeaf) {
          item.isChecked = grantedPermissionNames.find((p) => p === item.key) ? true : false;
          leafPermissionDict[item.key] = true;
        }
      });

      // 将非叶子节点的权限从选中项中移除,避免直接checked
      const newGrantedPermissionNames: string[] = [];
      for (const grantedPermission of grantedPermissionNames) {
        if (!leafPermissionDict[grantedPermission]) {
          continue;
        }
        newGrantedPermissionNames.push(grantedPermission);
      }
      this.grantedPermissionNames = newGrantedPermissionNames;
    },
    /**
     * 重新加载
     */
    reload(): void {
      this.loading = true;
      this.arrToTreeNode(this.checkedPermissions);
      this.onFilterChange('');
      this.loading = false;
    },
    /** 筛选条件发生改变 */
    onFilterChange(filterText: string) {
      // 匹配的项
      const filterList = this.permissions.filter((item) => {
        if (item.displayName!.indexOf(filterText) > -1 && item.parentName) {
          return true;
        }
        return false;
      });

      // 展开的项
      const expanded = [...new Set(filterList.map((o) => o.parentName))] as any[];
      this.expandedKeys = expanded;
      this.autoExpandParent = true;
      this.filterText = filterText;

      // 滑动到对应位置
      this.$nextTick(() => {
        setTimeout(() => {
          const treeRef = this.$refs.tree as any;
          if (!treeRef) {
            return;
          }
          if (filterList.length > 0 && filterText !== '') {
            treeRef.scrollTo({ key: filterList[0].name });
          } else {
            treeRef.scrollTo({ key: 0 });
          }
        }, 50);
      });
    },
    /**
     * 选中
     */
    onCheck(val: string[]) {
      this.checkedPermissions = this.processCheckedData(val);
      this.$emit('selectedPermissionsChange', this.checkedPermissions);
    },
    /** 处理选中的数据，获取父级权限 */
    processCheckedData(permissionNames: string[]): string[] {
      if (!Array.isArray(permissionNames)) {
        permissionNames = [];
      }

      // 当前选中项
      const checkedPermissions = [...permissionNames];

      // 选中项的字典
      const checkedPermissionDict: { [key: string]: boolean } = {};
      for (const permission of checkedPermissions) {
        checkedPermissionDict[permission] = true;
      }

      // 传入的权限名称
      for (const permissionName of permissionNames) {
        this.visitParent(permissionName, checkedPermissions, checkedPermissionDict);
      }

      return checkedPermissions;
    },
    /** 递归填充父级名称 */
    visitParent(
      permissionName: string,
      checkedPermissions: string[],
      checkedPermissionDict: { [key: string]: boolean }
    ) {
      const permission = this.permissionsDict[permissionName];
      if (!permission) {
        return;
      }
      if (permission.name !== permissionName) {
        return;
      }

      if (permission.parentName && !checkedPermissionDict[permission.parentName]) {
        checkedPermissionDict[permission.parentName] = true;
        checkedPermissions.push(permission.parentName);

        this.visitParent(permission.parentName, checkedPermissions, checkedPermissionDict);
      }
    },
    /** 获取传入的，默认选中的权限 */
    getDefaultSelectedPermissions(): string[] {
      if (!Array.isArray(this.defaultSelectedPermissions)) {
        return [];
      }

      return this.defaultSelectedPermissions as string[];
    },
    /** 展开项发生改变 */
    onExpand(keys: string[]) {
      this.expandedKeys = keys;
      this.autoExpandParent = false;
    }
  }
});
